package org.activequant.core.domainmodel.marketscanner;
import static org.activequant.util.tools.IdentityUtils.safeCompare;
import static org.activequant.util.tools.IdentityUtils.safeHashCode;

import java.io.Serializable;

import org.activequant.core.types.TimeFrame;
import org.activequant.core.types.TimeStamp;
import org.activequant.util.tools.IdentityUtils;


/**
* Specifies a sublist of marketscan entities for a given scancriteria specification.
* E.g. a marketscan series is defined by it's scanCriteria, start (timestamp)
* end (timestamp)  and resolution (timeframe)
* <br>
* Holds the following associated variables:
* <ul>
* <li>scanCriteria(ScanCriteria)</li>
* <li>startTimeStamp(TimeStamp)</li>
* <li>endTimeStamp(TimeStamp)</li>
* <li>timeFrame(TimeFrame)</li>
* </ul>
*  @author dmisev
*/
public class MarketScanSeriesSpecification implements Comparable<MarketScanSeriesSpecification>, Serializable {

private static final long serialVersionUID = -2190464710376768025L;
/**
 * private ScanCriteria scanCriteria;
 */
private ScanCriteria scanCriteria;
/**
 * private TimeStamp startTimeStamp;
 */
private TimeStamp startTimeStamp;
/**
 * private TimeStamp endTimeStamp;
 */
private TimeStamp endTimeStamp;
/**
 * private TimeFrame timeFrame;
 */
private TimeFrame timeFrame;
/**
 * empty constructor
 */
public MarketScanSeriesSpecification() {

}
/**
 * Constructs a MarketScanSeriesSpecification using the given scanCriteria(ScanCriteria) to set its associated scanCriteria(ScanCriteria).<br/>
 * Sets its associated startTimeStamp(TimeStamp) with the given startDate(TimeStamp).<br/>
 * Sets its associated endTimeStamp(TimeStamp) with the given endDate(TimeStamp).<br/>
 * Sets its associated timeFrame(TimeFrame) with the given timeFrame(TimeFrame).
 * @param scanCriteria
 * @param startDate
 * @param endDate
 * @param timeFrame
 */
public MarketScanSeriesSpecification(ScanCriteria scanCriteria, TimeStamp startDate, TimeStamp endDate, TimeFrame timeFrame) {
	this.scanCriteria = scanCriteria;
	this.startTimeStamp = startDate;
	this.endTimeStamp = endDate;
	this.timeFrame = timeFrame;
}
/**
 * Constructs a MarketScanSeriesSpecification using the given scanCriteria(ScanCriteria) to set its associated scanCriteria(ScanCriteria).
 * @param scanCriteria
 */
public MarketScanSeriesSpecification(ScanCriteria scanCriteria) {
	this.scanCriteria = scanCriteria;
}

/**
 * Constructs a copy MarketScanSeriesSpecification of the given marketScanSeriesSpecification(MarketScanSeriesSpecification)
 * Copy constructor.
 * @param spec
 */
public MarketScanSeriesSpecification(MarketScanSeriesSpecification marketScanSeriesSpecification) {
	this.scanCriteria = new ScanCriteria(marketScanSeriesSpecification.getScanCriteria());
	this.timeFrame = marketScanSeriesSpecification.timeFrame;
	this.startTimeStamp = marketScanSeriesSpecification.getStartTimeStamp();
	this.endTimeStamp = marketScanSeriesSpecification.getEndTimeStamp();
}
/**
 * Constructs a MarketScanSeriesSpecification using the given scanCriteria(ScanCriteria) to set its associated scanCriteria(ScanCriteria).<br/>
 * Sets its associated timeFrame(TimeFrame) with the given timeFrame(TimeFrame).
 * @param scanCriteria
 * @param timeFrame
 */
public MarketScanSeriesSpecification(ScanCriteria scanCriteria, TimeFrame timeFrame) {
	this.scanCriteria = scanCriteria;
	this.timeFrame = timeFrame;
}
/**
 * returns the associated endTimeStamp(TimeStamp)
 * @return
 */
public TimeStamp getEndTimeStamp() {
	return endTimeStamp;
}
/**
 * sets the associated endTimeStamp(TimeStamp) with the given end(TimeStamp)
 * @param end
 */
public void setEndTimeStamp(TimeStamp end) {
	this.endTimeStamp = end;
}
/**
 * returns the associated startTimeStamp(TimeStamp)
 * @return
 */
public TimeStamp getStartTimeStamp() {
	return startTimeStamp;
}
/**
 * sets the associated startTimeStamp(TimeStamp) with the given start(TimeStamp)
 * @param start
 */
public void setStartTimeStamp(TimeStamp start) {
	this.startTimeStamp = start;
}
/**
 * returns the associated timeFrame(TimeFrame)
 * @return
 */
public TimeFrame getTimeFrame() {
	return timeFrame;
}
/**
 * sets the associated timeFrame(TimeFrame) with the given timeFrame(TimeFrame)
 * @param timeFrame
 */
public void setTimeFrame(TimeFrame timeFrame) {
	this.timeFrame = timeFrame;
}
/**
 * Returns a string in the form "${scanCriteria} \t ${startTimeStamp} \t ${endTimeStamp}"
 */
public String toString() {
	return scanCriteria.toString() + " \t " + startTimeStamp + " \t " + endTimeStamp;
}
/**
 * returns the associated scanCriteria(ScanCriteria)
 * @return
 */
public ScanCriteria getScanCriteria() {
	return scanCriteria;
}
/**
 * sets the associated scanCriteria(ScanCriteria) with the given scanCriteria(ScanCriteria)
 * @param scanCriteria
 */
public void setScanCriteria(ScanCriteria scanCriteria) {
	this.scanCriteria = scanCriteria;
}

/**
 * {@inheritDoc}
 */
public int hashCode() {
	// ATTENTION: keep in sync with compareTo()
	return safeHashCode(this.scanCriteria) 
		+ safeHashCode(this.startTimeStamp)
		+ safeHashCode(this.endTimeStamp)
		+ safeHashCode(this.timeFrame);
}

/**
 * {@inheritDoc}
 */
public int compareTo(MarketScanSeriesSpecification other) {
	// ATTENTION: keep in sync with hashCode();
	int rc;
	
	rc = safeCompare(this.scanCriteria, other.scanCriteria);
	if(rc != 0) return rc;
	rc = safeCompare(this.startTimeStamp, other.startTimeStamp);
	if(rc != 0) return rc;
	rc = safeCompare(this.endTimeStamp, other.endTimeStamp);
	if(rc != 0) return rc;
	rc = safeCompare(this.timeFrame, other.timeFrame);
	
	return rc;
}

/**
 * {@inheritDoc}
 */
@Override
public boolean equals(Object other) {
	// NOTE: delegates to compareTo()
	return IdentityUtils.equalsTo(this, other);
}

}